<template>
  <div class="p-2">
    <el-form :model="queryParams" v-show="showSearch" :inline="true" label-width="68px">
      <el-form-item label="角色名称" prop="roleName">
        <el-input v-model="queryParams.roleName" placeholder="请输入角色名称" clearable style="width: 240px"
          @keyup.enter="fetchTableData" />
      </el-form-item>
      <el-form-item label="权限字符" prop="roleKey">
        <el-input v-model="queryParams.roleKey" placeholder="请输入权限字符" clearable style="width: 240px"
          @keyup.enter="fetchTableData" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="fetchTableData">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    <div class="flex justify-between">
      <el-button type="primary" plain icon="Plus" @click="handleAdd" v-permission="['system.role.add']">新增</el-button>
      <div>
        <el-tooltip effect="dark" :content="showSearch ? '隐藏搜索' : '展示搜索'" placement="top">
          <el-button circle icon="Search" @click="showSearch = !showSearch" loop="展示搜索" />
        </el-tooltip>
        <el-tooltip effect="dark" content="刷新" placement="top">
          <el-button circle icon="RefreshLeft" @click="fetchTableData" />
        </el-tooltip>
      </div>
    </div>
    <el-table v-loading="loading" :data="roleList" style="width: 100%" class="mt-2">
      <el-table-column prop="roleId" label="角色编号" width="120" />
      <el-table-column prop="roleName" label="角色名称" width="180" />
      <el-table-column prop="roleKey" label="权限字符" width="180" />
      <el-table-column prop="roleSort" label="排序" width="120" />
      <el-table-column prop="createTime" label="创建时间" width="180" />
      <el-table-column label="操作">
        <template #default="scope">
          <el-button v-if="scope.row.roleId !== 1" type="primary" icon="Edit" link
            v-permission="['system.role.edit']"
            @click="handleEdit(scope.row)">编辑</el-button>
          <el-button v-if="scope.row.roleId !== 1" type="primary" icon="Delete" link
            v-permission="['system.role.remove']"
            @click="handleDelete(scope.row)">删除</el-button>
          <el-button v-if="scope.row.roleId !== 1" type="primary" icon="CircleCheck" link
            v-permission="['system.role.assign']"
            @click="handleAssign(scope.row)">分配权限</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination class="justify-end mt-4 d-flex" v-model:current-page="queryParams.pageNum"
      v-model:page-size="queryParams.pageSize" :page-sizes="[10, 20, 30, 50]"
      layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="fetchTableData"
      @current-change="fetchTableData" />
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="30%" :before-close="handleClose">
      <el-form ref="formRef" :model="roleForm" :rules="rules" label-width="120px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="roleForm.roleName" />
        </el-form-item>
        <el-form-item label="权限字符" prop="roleKey">
          <el-input v-model="roleForm.roleKey" />
        </el-form-item>
        <el-form-item label="排序" prop="roleSort">
          <el-input type="number" v-model="roleForm.roleSort" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleClose">取消</el-button>
          <el-button type="primary" @click="submitForm(formRef)">
            确认
          </el-button>
        </span>
      </template>
    </el-dialog>

    <el-dialog v-model="assignDialogVisible" title="分配权限" width="50%" :before-close="handleAssignClose">
      <el-form ref="formRef" :model="assignRoleForm"  label-width="120px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="assignRoleForm.roleName" disabled />
        </el-form-item>
        <el-form-item label="菜单权限">
          <el-tree
            ref="menuTreeRef"
            :data="assignRoleForm.menuTrees"
            show-checkbox
            node-key="menuId"
            :default-expanded-keys="assignRoleForm.expandedMenuIds"
            :default-checked-keys="assignRoleForm.checkedMenuIds"
            :props="defaultProps"
            :check-strictly="true"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleAssignClose">取消</el-button>
          <el-button type="primary" @click="handleAssignSubmit">
            确认
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { ElMessageBox, ElMessage } from "element-plus";
import {
  getRoleList,
  addRole,
  updateRole,
  deleteRole,
  getRoleMenuTree,
  assignRoleMenu
} from "@/api/system/role";
const assignDialogVisible = ref(false);
const menuTreeRef = ref(null);
const formRef = ref(null);
const loading = ref(false);
const showSearch = ref(true);
const total = ref(0);
const roleList = ref([]);
const dialogVisible = ref(false);
const dialogTitle = ref("");
const rules = ref({
  roleName: [{ required: true, message: "请输入角色名称", trigger: "blur" }],
  roleKey: [{ required: true, message: "请输入权限字符", trigger: "blur" }],
  roleSort: [{ required: true, message: "请输入排序", trigger: "blur" }],
});
const defaultProps = {
  children: 'children',
  label: 'label',
}
// 查询参数
const queryParams = ref({
  pageNum: 1,
  pageSize: 10,
  roleName: "",
  roleKey: "",
});
// 角色表单数据
const roleForm = ref({
  roleId: null,
  roleName: "",
  roleKey: "",
  roleSort: 10,
});
// 权限表单数据
const assignRoleForm = ref({
  roleId: null,
  roleName: "",
  menuIds: [],
  menuTrees: [],
  expandedMenuIds: [],
  checkedMenuIds: [],
});
// 关闭分配权限弹窗
function handleAssignClose() {
  assignDialogVisible.value = false;
  assignRoleForm.value = {
    roleId: null,
    roleName: "",
    menuIds: [],
    menuTrees: [],
    expandedMenuIds: [],
    checkedMenuIds: []
  };
}
// 提交分配权限表单
async function handleAssignSubmit() {
  assignRoleForm.value.menuIds = getCheckedNodes();
  await assignRoleMenu(assignRoleForm.value);
  handleAssignClose();
}
// 获取所有选中的节点（不包含半选节点）
const getCheckedNodes = () => {
  if (!menuTreeRef.value) return [];
  // 参数：includeHalfChecked（默认 false，不包含半选节点）
  const ans = [];
  menuTreeRef.value.getCheckedNodes().forEach(element => {
    ans.push(element.menuId);
  });
  return ans;
};

// 关闭角色弹窗
function handleClose() {
  resetRoleForm();
  dialogVisible.value = false;
}
// 提交角色表单
function submitForm(formRef) {
  formRef.validate().then(async () => {
    if (roleForm.value.roleId) {
      await updateRole(roleForm.value);
    } else {
      await addRole(roleForm.value);
    }
    dialogVisible.value = false;
    resetRoleForm();
    fetchTableData();
  });
}
// 充值角色表单
function resetRoleForm() {
  roleForm.value = {
    roleId: null,
    roleName: "",
    roleKey: "",
    roleSort: 10,
  };
}
function handleAdd() {
  dialogTitle.value = "新增角色";
  dialogVisible.value = true;
}
function handleEdit(row) {
  roleForm.value = row;
  dialogTitle.value = "编辑角色";
  dialogVisible.value = true;
}
function handleDelete(row) {
  ElMessageBox.confirm("确定删除吗？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    await deleteRole(row.roleId);
    fetchTableData();
  });
}
async function handleAssign(row) {
  const res = await getRoleMenuTree(row.roleId);
  assignRoleForm.value.roleId = row.roleId;
  assignRoleForm.value.roleName = row.roleName;
  assignRoleForm.value.menuTrees = res.menuTrees;
  assignRoleForm.value.expandedMenuIds = res.expandedMenuIds;
  assignRoleForm.value.checkedMenuIds = res.checkedMenuIds;
  assignDialogVisible.value = true;
}
// 重制查询
async function resetQuery() {
  queryParams.value = {
    pageNum: 1,
    pageSize: 10,
    roleName: "",
    roleKey: "",
  };
  fetchTableData();
}
// 查询角色
async function fetchTableData() {
  loading.value = true;
  const res = await getRoleList(queryParams.value);
  roleList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}

onMounted(() => {
  fetchTableData();
});
</script>
<style scoped></style>
